準備考試,速速解決。先跳過21,感覺花的時間比較多。
    const links = document.querySelectorAll('a')
    const highlight = document.createElement('span')
    highlight.classList.add('highlight')
    document.body.append(highlight)
    function highlightLink(){
      const linkCord = this.getBoundingClientRect()
      highlight.style.width = `${linkCord.width}px`
      highlight.style.height = `${linkCord.height}px`
      highlight.style.transform = `translate(${linkCord.left+window.scrollX}px,${linkCord.top+window.scrollY}px)`
    }
    links.forEach( a => a.addEventListener('mouseenter', highlightLink))
const msg = new SpeechSynthesisUtterance();
  let voices = [];
  const voicesDropdown = document.querySelector('[name="voice"]');
  const options = document.querySelectorAll('[type="range"], [name="text"]');
  const speakButton = document.querySelector('#speak');
  const stopButton = document.querySelector('#stop');
  msg.text = document.querySelector('[name="text"]').value;
  function populateVoice(){
    voices = this.getVoices()
    voicesDropdown.innerHTML = voices
        .map(voice => `<option value='${voice.name}'>${voice.name}(${voice.lang})</option>`)
        .join(" ")
  }
  function setVoice(){
    msg.voice = voices.find(voice => voice.name ===this.value)
    toggle()
  }
  function toggle() {
    speechSynthesis.cancel()
    speechSynthesis.speak(msg)
  }
  speechSynthesis.addEventListener('voiceschanged',populateVoice)
  voicesDropdown.addEventListener('change',setVoice)